package com.iplant.base.utils.general;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

public class CalendarTool {

    public static Calendar getCalendar(long millis) {
        Calendar wResult = Calendar.getInstance();
        wResult.setTimeInMillis(millis);
        return wResult;
    }

    public static Calendar getNow() {

        return Calendar.getInstance();
    }

    public static Calendar getDateNow() {

        return getDate(Calendar.getInstance());
    }

    /**
     * 获取2000-1-1
     *
     * @return
     */
    public static Calendar getBasicDate() {

        return getCalendar(2000, 0, 1);
    }

    public static int CompareDate(Calendar wCalendar, Calendar cal) {
        if (wCalendar == null)
            wCalendar = UsedDate;
        if (cal == null)
            cal = UsedDate;
        return CalendarTool.CloneDate(wCalendar).compareTo(CalendarTool.CloneDate(cal));
    }

    public static int CompareDate(String wCalendar, String cal, String wFormat) {

        Calendar wCalendar1 = StringUtils.parseCalendar(wCalendar, wFormat);
        Calendar cal1 = StringUtils.parseCalendar(cal, wFormat);

        return CompareDate(wCalendar1, cal1);
    }

    public static int CompareDate(String wCalendar, String cal) {
        return CompareDate(wCalendar, cal, "yyyy-MM-dd");
    }

    private static Calendar UsedDate = getCalendar(2020, 0, 1);

    public static Calendar getUsedDate() {

        return UsedDate;
    }

    public static Calendar getDate(Calendar wCalendar) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wCalendar.get(Calendar.YEAR), wCalendar.get(Calendar.MONTH), wCalendar.get(Calendar.DAY_OF_MONTH),
                0, 0, 0);
        wResult.set(Calendar.MILLISECOND, 0);
        return wResult;
    }
    public static Calendar getYear(Calendar wCalendar) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wCalendar.get(Calendar.YEAR),0, 1,
                0, 0, 0);
        wResult.set(Calendar.MILLISECOND, 0);
        return wResult;
    }
    public static Calendar getMonth(Calendar wCalendar) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wCalendar.get(Calendar.YEAR), wCalendar.get(Calendar.MONTH), 1,
                0, 0, 0);
        wResult.set(Calendar.MILLISECOND, 0);
        return wResult;
    }

    public static Calendar getDate() {
        Calendar wResult = Calendar.getInstance();
        wResult.set(Calendar.HOUR_OF_DAY, 0);
        wResult.set(Calendar.MINUTE, 0);
        wResult.set(Calendar.SECOND, 0);
        wResult.set(Calendar.MILLISECOND, 0);
        return wResult;
    }

    public static Calendar getDateMaxMill() {
        Calendar wResult = Calendar.getInstance();
        wResult.set(Calendar.HOUR_OF_DAY, 23);
        wResult.set(Calendar.MINUTE, 59);
        wResult.set(Calendar.SECOND, 59);
        wResult.set(Calendar.MILLISECOND, 999);
        return wResult;
    }

    public static Calendar getCalendar(int wYear, int wMonth, int wDate) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wYear, wMonth, wDate, 0, 0, 0);
        wResult.set(Calendar.MILLISECOND, 0);
        return wResult;
    }


    public static Calendar getTime(int... wTimes) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(Calendar.MILLISECOND, 0);
        if (wTimes != null && wTimes.length > 0) {

            wResult.set(Calendar.HOUR_OF_DAY, wTimes[0]);
            if (wTimes.length > 1) {
                wResult.set(Calendar.MINUTE, wTimes[1]);
            } else {
                wResult.set(Calendar.MINUTE, 0);
            }
            if (wTimes.length > 2) {
                wResult.set(Calendar.SECOND, wTimes[2]);
            } else {
                wResult.set(Calendar.SECOND, 0);
            }
            if (wTimes.length > 3) {
                wResult.set(Calendar.MILLISECOND, wTimes[3]);
            }
        }
        return wResult;
    }

    public static Calendar CloneMonth(Calendar wCalendar, int wDate, int... wTimes) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wCalendar.get(Calendar.YEAR), wCalendar.get(Calendar.MONTH),
                wDate, 0, 0, 0);
        wResult.set(Calendar.MILLISECOND, 0);
        if (wTimes != null && wTimes.length > 0) {

            wResult.set(Calendar.HOUR_OF_DAY, wTimes[0]);
            if (wTimes.length > 1) {
                wResult.set(Calendar.MINUTE, wTimes[1]);
            }
            if (wTimes.length > 2) {
                wResult.set(Calendar.SECOND, wTimes[2]);
            }
            if (wTimes.length > 3) {
                wResult.set(Calendar.MILLISECOND, wTimes[3]);
            }
        }
        return wResult;
    }

    public static Calendar CloneDate(Calendar wCalendar, int... wTimes) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wCalendar.get(Calendar.YEAR), wCalendar.get(Calendar.MONTH),
                wCalendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        wResult.set(Calendar.MILLISECOND, 0);
        if (wTimes != null && wTimes.length > 0) {

            wResult.set(Calendar.HOUR_OF_DAY, wTimes[0]);
            if (wTimes.length > 1) {
                wResult.set(Calendar.MINUTE, wTimes[1]);
            } else {
                wResult.set(Calendar.MINUTE, 0);
            }
            if (wTimes.length > 2) {
                wResult.set(Calendar.SECOND, wTimes[2]);
            } else {
                wResult.set(Calendar.SECOND, 0);
            }
            if (wTimes.length > 3) {
                wResult.set(Calendar.MILLISECOND, wTimes[3]);
            }
        }
        return wResult;
    }

    public static Calendar AddCalendar(Calendar wCalendar, int wCF, int wValue) {
        Calendar wResult = CloneDateTime(wCalendar);
        wResult.add(wCF, wValue);
        return wResult;
    }

    public static Calendar CloneTime(Calendar wCalendar) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(UsedDate.get(Calendar.YEAR), UsedDate.get(Calendar.MONTH),
                UsedDate.get(Calendar.DAY_OF_MONTH), wCalendar.get(Calendar.HOUR_OF_DAY),
                wCalendar.get(Calendar.MINUTE), wCalendar.get(Calendar.SECOND));
        wResult.set(Calendar.MILLISECOND, 0);
        return wResult;
    }

    public static Calendar CloneDateTime(Calendar wCalendar) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wCalendar.get(Calendar.YEAR), wCalendar.get(Calendar.MONTH),
                wCalendar.get(Calendar.DAY_OF_MONTH), wCalendar.get(Calendar.HOUR_OF_DAY),
                wCalendar.get(Calendar.MINUTE), wCalendar.get(Calendar.SECOND));
        wResult.set(Calendar.MILLISECOND, 0);
        return wResult;
    }

    public static Calendar CloneTime(int wYear, int wMonth, int wDay, Calendar wCalendar) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wYear, wMonth, wDay, wCalendar.get(Calendar.HOUR_OF_DAY),
                wCalendar.get(Calendar.MINUTE), wCalendar.get(Calendar.SECOND));
        wResult.set(Calendar.MILLISECOND, 0);
        return wResult;
    }

    public static Calendar CloneDateAndTime(Calendar wDate, Calendar wTime) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wDate.get(Calendar.YEAR), wDate.get(Calendar.MONTH),
                wDate.get(Calendar.DAY_OF_MONTH), wTime.get(Calendar.HOUR_OF_DAY),
                wTime.get(Calendar.MINUTE), wTime.get(Calendar.SECOND));
        wResult.set(Calendar.MILLISECOND, wTime.get(Calendar.MILLISECOND));
        return wResult;
    }


    public static Calendar getCalendar(int wYear, int wMonth, int wDate, int... wTimes) {
        Calendar wResult = Calendar.getInstance();
        wResult.set(wYear, wMonth, wDate, 0, 0, 0);
        wResult.set(Calendar.MILLISECOND, 0);

        if (wTimes != null && wTimes.length > 0) {

            wResult.set(Calendar.HOUR_OF_DAY, wTimes[0]);
            if (wTimes.length > 1) {
                wResult.set(Calendar.MINUTE, wTimes[1]);
            } else {
                wResult.set(Calendar.MINUTE, 0);
            }
            if (wTimes.length > 2) {
                wResult.set(Calendar.SECOND, wTimes[2]);
            } else {
                wResult.set(Calendar.SECOND, 0);
            }
            if (wTimes.length > 3) {
                wResult.set(Calendar.MILLISECOND, wTimes[3]);
            }
        }

        return wResult;
    }

    public static int getShiftID(Calendar wCalendar) {
        return StringUtils.parseInt(StringUtils.parseCalendarToString(wCalendar, "yyyyMMdd"));

    }

    public static int getShiftID() {
        return StringUtils.parseInt(StringUtils.parseCalendarToString(Calendar.getInstance(), "yyyyMMdd"));

    }

    public static long SubMilliseconds(Calendar wCalendar1, Calendar wCalendar2) {
        if (wCalendar1 == null || wCalendar2 == null) {
            return 0;
        }
        return wCalendar1.getTime().getTime() - wCalendar2.getTime().getTime();
    }

    public static long SubSeconds(Calendar wCalendar1, Calendar wCalendar2) {
        if (wCalendar1 == null || wCalendar2 == null) {
            return 0;
        }
        return (wCalendar1.getTime().getTime() - wCalendar2.getTime().getTime()) / 1000;
    }


    public static int SubDate(Calendar wCalendar1, Calendar wCalendar2) {
        if (wCalendar1 == null || wCalendar2 == null) {
            return 0;
        }
        wCalendar1 = getDate(wCalendar1);
        wCalendar2 = getDate(wCalendar2);

        return (int) ((wCalendar1.getTime().getTime() - wCalendar2.getTime().getTime()) / (1000 * 3600 * 24));
    }

    public static int SubMonth(Calendar wCalendar1, Calendar wCalendar2) {
        if (wCalendar1 == null || wCalendar2 == null) {
            return 0;
        }

        return (wCalendar1.get(Calendar.YEAR) - wCalendar2.get(Calendar.YEAR)) * 12
                + (wCalendar1.get(Calendar.MONTH) - wCalendar2.get(Calendar.MONTH));

    }

    public static Calendar getMondayOfCurrentWeek() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        int currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (currentDayOfWeek > 2) {
            calendar.add(Calendar.DATE, -currentDayOfWeek + 2);
        } else if (currentDayOfWeek < 2) {
            calendar.add(Calendar.DATE, -6);
        }
        return calendar;
    }

    public static Calendar getSundayOfCurrentWeek() {
        Calendar wMonday = getMondayOfCurrentWeek();
        wMonday.add(Calendar.DATE, 6);
        return wMonday;
    }

    public static Calendar getMinTimeOfCurrentWeek() {
        Calendar wDate = getMondayOfCurrentWeek();
        wDate.set(Calendar.HOUR_OF_DAY, 0);
        wDate.set(Calendar.MINUTE, 0);
        wDate.set(Calendar.SECOND, 0);
        wDate.set(Calendar.MILLISECOND, 0);
        return wDate;
    }

    public static Calendar getMaxTimeOfCurrentWeek() {
        Calendar wDate = getSundayOfCurrentWeek();
        wDate.set(Calendar.HOUR_OF_DAY, 23);
        wDate.set(Calendar.MINUTE, 59);
        wDate.set(Calendar.SECOND, 59);
        wDate.set(Calendar.MILLISECOND, 999);
        return wDate;
    }

    public static Calendar getMinTimeOfCurrentMonth() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
    }

    public static Calendar getMaxTimeOfCurrentMonth() {
        Calendar calendar = getMinTimeOfCurrentMonth();
        calendar.add(Calendar.MONTH, 1);
        calendar.add(Calendar.SECOND, -1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar;
    }
}
